Skip to content

feat: add native GroupsAccumulator for any_value - #23065

Draft
yinli-systems wants to merge 8 commits into
apache:mainfrom
yinli-systems:kevin/any-value-groups-accumulator
Draft

feat: add native GroupsAccumulator for any_value#23065
yinli-systems wants to merge 8 commits into
apache:mainfrom
yinli-systems:kevin/any-value-groups-accumulator

Conversation

@yinli-systems

@yinli-systems yinli-systems commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Follow-up to #23043, which is now merged.

Rationale for this change

Grouped any_value falls back to GroupsAccumulatorAdapter, creating one boxed accumulator per group and materializing per-group slices. That overhead dominates high-cardinality GROUP BY workloads even though any_value only retains one non-null value per group.

What changes are included?

  • A native GroupsAccumulator that scans each batch once, supports filters and partial-state merging, preserves the existing two-column state contract, supports EmitTo::First, and implements convert_to_state.
  • Native Vec<T::Native> state for numeric, decimal, temporal, and timestamp Arrow primitive types.
  • Allocation-aware byte state for Utf8, LargeUtf8, Utf8View, Binary, LargeBinary, and BinaryView, reusing the existing first/last state container rather than storing one ScalarValue per group.
  • A generic ScalarValue fallback for remaining supported Arrow types.
  • Six focused unit tests covering nulls, filters, merge, conversion, partial emission, primitives, and string/binary view types.
  • Criterion comparison against GroupsAccumulatorAdapter.

This completes the review suggestion to specialize primitive and binary/view types.

Validation

  • cargo fmt --all --check
  • cargo test -p datafusion-functions-aggregate --lib (164 passed)
  • cargo clippy -p datafusion-functions-aggregate --all-targets --no-deps -- -D warnings
  • cargo bench -p datafusion-functions-aggregate --bench any_value -- --noplot
  • git diff upstream/main --check for the five-file PR diff

Local Apple Silicon benchmark medians (8,192 rows / 4,096 groups):

Type Native Adapter Improvement
Int64 10.32 µs 1.29 ms ~125×
Utf8 90.7 µs 1.40 ms ~15×

Running Clippy without --no-deps is currently blocked by an unrelated dead-code warning for DynamicFilterPhysicalExpr::from_parts on current main; the target crate itself passes with warnings denied.

AI assistance

AI tooling assisted with implementation and validation. I reviewed the final accumulator/state flow, the reviewer feedback, and the benchmark design, and ran the validations listed above.

Kevin-Li-2025 added 4 commits June 19, 2026 13:14
@github-actions github-actions Bot added sqllogictest SQL Logic Tests (.slt) functions Changes to functions implementation labels Jun 21, 2026

#[derive(Debug)]
struct AnyValueGroupsAccumulator {
values: Vec<ScalarValue>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be worth specializing for primitive / binary (view) types to save further memory / allocations

@yinli-systems

Copy link
Copy Markdown
Contributor Author

Addressed the primitive specialization feedback by adding a native primitive any_value groups accumulator for numeric, decimal, temporal, and timestamp types.

The new path stores group state as a native Vec<T::Native> plus the existing is_set bitmap, and only falls back to the ScalarValue-based accumulator for non-primitive/complex types. This keeps the existing generic behavior while avoiding per-group ScalarValue state for the common primitive cases.

Validation run locally:

  • cargo fmt --check
  • cargo test -p datafusion-functions-aggregate any_value --lib
  • git diff --check

@github-actions github-actions Bot removed the sqllogictest SQL Logic Tests (.slt) label Jul 23, 2026
@codecov-commenter

codecov-commenter commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 67.52941% with 138 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.73%. Comparing base (2fb472a) to head (a81ecec).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
datafusion/functions-aggregate/src/any_value.rs 67.52% 96 Missing and 42 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #23065      +/-   ##
==========================================
- Coverage   80.75%   80.73%   -0.02%     
==========================================
  Files        1096     1096              
  Lines      373605   374030     +425     
  Branches   373605   374030     +425     
==========================================
+ Hits       301713   301985     +272     
- Misses      53890    53998     +108     
- Partials    18002    18047      +45     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

# Conflicts:
#	datafusion/functions-aggregate/Cargo.toml
Signed-off-by: Kevin-Li-2025 <kxl474@student.bham.ac.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants